package com.gem.day19;

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import com.google.common.collect.Lists;

/**
 * 本类用来演示Java第三方XML解析组件Dom4J解析XML文档以及写入XML文档
 * 
 * @author easonsy
 * 2020年8月17日 下午2:40:25
 */
public class StudentDom4jParser {
	public static void main(String[] args) {

		//解析XML
		/*try {
			parseXml("D:\\workspace\\202007JavaSE\\src\\com\\gem\\day19\\students.xml").forEach(System.out::println);
		} catch (DocumentException e) {
			e.printStackTrace();
		}*/

		//生成xml文档
		Student student1 = new Student(1L, "AA", LocalDate.now(), Gender.FEMALE);
		Student student2 = new Student(2L, "BB", LocalDate.now(), Gender.MALE);
		Student student3 = new Student(3L, "CC", LocalDate.now(), Gender.FEMALE);
		List<Student> students = Lists.newArrayList(student1, student2, student3);
		writeXml(students, "D:\\students.xml");
	}

	/**
	 * 把内存中的Java对象写入到本地磁盘生成XML文档
	 */
	public static void writeXml(List<Student> students, String filePath) {
		//创建文档树对象
		Document document = DocumentHelper.createDocument();
		//添加根节点
		Element root = document.addElement("students");
		//遍历集合[省去非空判断]
		for (Student student : students) {
			//每遍历到一个学生对象就向文档树上添加一个学生元素
			Element studentElement = root.addElement("student");
			//设置属性
			studentElement.addAttribute("id", student.getId() + "");
			//设置子元素
			studentElement.addElement("name").setText(student.getName());
			studentElement.addElement("birthday").setText(student.getBirthday().toString());
			studentElement.addElement("gender").setText(student.getGender().toString());
		}
		//输出
		try (Writer writer = new FileWriter(filePath)) {
			OutputFormat format = new OutputFormat();
			format.setIndent(true);
			format.setIndentSize(5);
			format.setNewlines(true);
			XMLWriter xmlWriter = new XMLWriter(writer, format);
			xmlWriter.write(document);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 解析指定路径下的XML文档
	 * @throws DocumentException 
	 */
	public static List<Student> parseXml(String xmlPath) throws DocumentException {
		List<Student> students = null;
		File file = new File(xmlPath);
		if (file.exists() && file.isFile() && file.getName().endsWith("xml")) {
			//获取Dom4J解析器
			SAXReader reader = new SAXReader();
			//获取DOM文档对象(内存中的文档对象)
			Document document = reader.read(file);
			//处理文档树对象
			students = processDocument(document);
		}
		return students;
	}

	/**
	 * 把内存中的文档对象模型转换成学生集合
	 */
	private static List<Student> processDocument(Document document) {
		Student student = null;
		List<Student> students = new ArrayList<>();
		//获取文档树根节点对象(students)
		Element rootElement = document.getRootElement();
		//迭代根元素下的一级节点
		Iterator<Element> elementIterator = rootElement.elementIterator();
		while (elementIterator.hasNext()) {
			//获取每一个student节点
			Element studentElement = elementIterator.next();
			//把每一个学生节点转换成学生对象
			student = processElement(studentElement);
			//把转换好的学生对象添加到结果集合中
			students.add(student);
		}
		return students;
	}

	/**
	 * 把学生节点转换成学生对象
	 */
	private static Student processElement(Element studentElement) {
		//获取属性值并且转换成对应的数据类型
		Long id = Long.parseLong(studentElement.attributeValue("id"));
		String name = studentElement.elementText("name");
		LocalDate birthday = LocalDate.parse(studentElement.elementText("birthday"));
		Gender gender = Enum.valueOf(Gender.class,
				"男".equals(studentElement.elementText("gender")) ? "MALE" : "FEMALE");
		Student student = new Student(id, name, birthday, gender);
		//判断学生是否有地址对象
		Element addressesElement = studentElement.element("addresses");
		if (addressesElement != null) {
			List<Address> addressList = new ArrayList<>();
			Address address = null;
			List<Element> addressElements = addressesElement.elements("address");
			for (Element addressElement : addressElements) {
				//获取每一个地址元素并且转换成地址对象
				address = new Address(addressElement.elementText("province"), addressElement.elementText("city"),
						addressElement.elementText("area"));
				addressList.add(address);
			}
			student.setAddresses(addressList);
		}
		return student;
	}
}
